import json
import sys

sys.path.append("../")
sys.path.append("../..")

from feature_set.app.id.app_id_gcate_v1.AppIdGCateV1 import AppIdGCateV1
from feature_set.app.id.app_id_ojk_v1.AppIdOJKV1 import AppIdOJKV1
from feature_set.app.id.app_id_comp_v1.AppIdCompV1 import AppIdCompV1
from feature_set.app.id.app_id_base_v1.AppIdBaseV1 import AppIdBaseV1
from feature_set.app.un.app_un_woe_v1.AppUnWoeV1 import AppUnWoeV1
from feature_set.sms.id.sms_id_base_v1.sms_id_base_v1 import SmsIdBaseV1
from feature_set.sms.un.sms_un_woe_v1.SmsUnWoeV1 import SmsUnWoeV1
from feature_set.cross.id.cross_id_base_v1.cross_id_base_v1 import CrossIdBaseV1
from feature_set.call.id.call_id_base0_v1.CallIdBase0V1 import CallIdBase0V1
from featurelib.common import *
feature_map = {
    "app_id_base_v1": AppIdBaseV1(),
    "app_id_comp_v1": AppIdCompV1(),
    "app_id_gcate_v1": AppIdGCateV1(),
    "app_id_ojk_v1":AppIdOJKV1(),
    "app_id_woe_v1_a3": AppUnWoeV1(conf_path='app/id/app_id_woe_v1/a3'),
    "app_id_woe_v1_a5": AppUnWoeV1(conf_path='app/id/app_id_woe_v1/a5'),
    "sms_id_base_v1": SmsIdBaseV1(),
    'sms_id_woe_v1_a3': SmsUnWoeV1('sms/id/sms_id_woe_v1/a4', 'english'),
    'sms_id_woe_v1_a5': SmsUnWoeV1('sms/id/sms_id_woe_v1/a4', 'english'),
    "call_id_base0_v1": CallIdBase0V1(),
    'cross_id_base_v1': CrossIdBaseV1()
}

import sys
import time
import traceback
import warnings
from concurrent.futures import ProcessPoolExecutor,as_completed

from flask import Flask, request
from nb_log import get_logger
import numpy as np


logger = get_logger(None)
app = Flask(__name__)


def featue_task(feature_generator,request_data:RequstData):
    try:
        rs = feature_generator.gen_features(request_data)
        return rs
    except Exception as e:
        logger.error(f"{request_data.order_id}特征模块{type(feature_generator)}计算失败,报错如下\n{traceback.format_exc()}")
        return {}

executor = ProcessPoolExecutor(max_workers=3)


import lightgbm as lgb
model2 = lgb.Booster(model_file='lgb_id_newmodel_v2.txt')
model5 = lgb.Booster(model_file='lgb_a5_score.txt')
feaList2 = model2.feature_name()
feaList5 = model5.feature_name()

monitor_flist2 = model_features(model2).head(50)['var'].to_list()
monitor_flist5 = model_features(model5).head(50)['var'].to_list()

monite_flist = monitor_flist2 + monitor_flist5

@app.route("/api/<path:model_name>", methods=["POST"])
def api(model_name):
    request_json = request.get_json()

    order_id, request_data = tranReq2featurelibData(request_json)

    task_list = [(gen_function, request_data, feature_name) for feature_name, gen_function in feature_map.items()]

    feature_dict = {}
    futures = {executor.submit(featue_task, gen_function, data): feature_name
                            for gen_function,data,feature_name in task_list}

    a = time.time()
    for future in as_completed(futures):
        feature_name = futures[future]
        data = future.result()
        new_dict = {  f"{feature_name}_{k}":v   for k,v in data.items() }
        feature_dict.update(new_dict)
    b = time.time()
    logger.info(f"{order_id}特征计算耗时:{b-a}s")

    monitor_fealist={}
    feature_list2 = []
    for f in feaList2:
        ff = feature_dict.get(f, -9999)
        try:
            ff = float(ff)
        except:
            ff = -9999
        feature_list2.append(ff)


    feature_list5 = []
    for f in feaList5:
        ff = feature_dict.get(f, -9999)
        try:
            ff = float(ff)
        except:
            ff = -9999
        feature_list5.append(ff)

    for f in monitor_flist2:
        ff = feature_dict.get(f, -9999)
        try:
            ff = float(ff)
        except:
            ff = -9999
        monitor_fealist.update({f: ff})

    prob2 = model2.predict([feature_list2])[0]
    score2 = float(round(550 - 60 / np.log(2) * np.log(prob2 / (1 - prob2)), 0))

    prob5 = model5.predict([feature_list5])[0]
    score5 = float(round(550 - 60 / np.log(2) * np.log(prob5 / (1 - prob5)), 0))

    # 规则模块
    applicant = request_data.applicant
    relatedUserCount = applicant.get("emergencyContactRuleInfo",{}).get("relatedUserCount",-999)
    loanAppInstallWithin72h = applicant.get("appStatisticInfo",{}).get("loanAppInstallWithin72h",-999)
    gender=applicant.get("gender", "")

    rule1 = score5 <=499
    rule2 = relatedUserCount>=1
    rule3 = (score5<=562) & (loanAppInstallWithin72h>=2)
    rule4 = (score5<=539) & (gender=='MALE')

    monitor_features = {  k: feature_dict.get(k, -9999)  for k in monitor_fealist }
    monitor_features.update({'a2_score_real':score2,'a2_prob_real':prob2,'a5_score_real':score5,'a5_prob_real':prob5
                                ,'rule1_hit':rule1,'rule2_hit':rule2,'rule3_hit':rule3,'rule4_hit':rule4,"applicant":applicant})

    if rule1 or rule2 or rule3 or rule4:
        score2 = 100
        prob2 = 1.1
    else:
        score2 = 900
        prob2 = 0.1

    c = time.time()
    logger.info(f"{order_id}模型计算耗时:{c-b}s")

    return  {"code": 200,
             "data":  {'a2_prob': prob2,
                       'a2_score':score2},
             'monitor_features':monitor_features}

if __name__ == '__main__':
    app.run(debug=False,host='0.0.0.0',port=8089)